/**
 * 通用下拉框
 * senvon
 * 依赖jquery1.7+
 * 下拉树,依赖ztree
 */
(function () {
	//在body里面注册全局事件
	//点击任何地方,都关闭panel
	$(window.document).click(function(event){
		//console.log("=========invoke body click ========");
		//发生的点击事件不属于当前picker的,对picker的panel进行隐藏处理
		var element = getTarget(event);
		var targetPickerDiv = $(element).closest(".Picker");
		$(".Picker .Panel").each(function(i , n){
			var hiddenPicker = $(this).closest(".Picker");
			if(targetPickerDiv.data("obj") != hiddenPicker.data("obj")){
				$(this).hide();
			}
		});
	});

	var AbstractPicker,FilterPicker,SimplePicker,
	copyProperty = function(child , parent){
		for (var key in parent) { 
			// if (hasProp.call(parent, key)) 
				child[key] = parent[key];
		}
	},
	bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
	/**
	 * 类的继承
	 * 不但会继承方法,属性也会继承
	 */
	extend = function(child, parent) { 
		copyProperty(child , parent);
		function ctor() { 
			this.constructor = child; 
		} 
		ctor.prototype = parent.prototype; 
		child.prototype = new ctor(); 
		child.__super__ = parent.prototype; 
		return child; 
	},
	hasProp = {}.hasOwnProperty
	,getTarget=function(ev){  //返回事件的实际目标
		return ev.target||ev.srcElement;
	 },
	preventDefault = function(ev){   //阻止事件的默认行为
		if(ev.preventDefault){
			ev.preventDefault(); 
		}else{
			ev.returnValue=false;
		}
	 }, 
	stopPropagation = function(ev){  //立即停止事件在DOM中的传播
				//避免触发注册在document.body上面的事件处理程序
		if(ev.stopPropagation){
			ev.stopPropagation();
		}else{
			ev.cancelBubble=true;
		}
	}
	;

	/**
	 * picker的基类
	 * 用于定义基本的picker框架
	 * 定义基本的picker的方法和属性配置
	 * 
	 * dom结构如下
	 * <div class="Picker">
	 * 	<input type="hidden" name="option.name"/>
	 * 	<div class="selectBox form-control">
	 * 		<ul class="selectText">
	 * 			<li></li>
	 * 		</ul>
	 * 		
	 * 		<div class="selectButton">
	 * 
	 * 		</div>
	 * 	</div>
	 * 	<div class="Panel">
	 * 		<div class="filter"><input></div>
	 * </div>
	 * </div>
	 * 
	 * 接受数据格式
	 * [{
	 * pid:"" , value:"" , text:""
	 * }]
	 * 
	 */
	AbstractPicker = (function () {
		function AbstractPicker(_option){
			this.option = {
				name: null,									//表单提交的字段名称
				defaultValue: null,							//页面渲染时的默认值
				data:{},									//本地数据
				url:"",
				urlData:{},
				convertData:{},								//远程或者本地data的转换
				mode:"single",								//single:单选,multi:多选
				filter:true,
				onfilter:{},								//过滤的回调函数,返回过滤的数据列表,如果还有convertData函数会onfilter的时候会被调用
				onselect: {}
			}
			copyProperty(this.option, _option || {});

			//私有变量需要定义在function内部
			this.pickerDiv = $("<div>").addClass("Picker").data("obj" , this);
			this.submitField = $("<input type='hidden' id='"+this.option.name+"' name='"+this.option.name+"'/>");
			if(this.option.defaultValue){
				submitField.val(this.option.defaultValue);
			}
			this.pickerDiv.append(this.submitField);

			this.selectBox = $("<div>").addClass("selectBox").addClass("form-control");
			this.selectText = $("<ul>").addClass("selectText");
			this.selectButton = $("<div>").addClass("selectButton");
			this.pickerDiv.append(this.selectBox.append(this.selectText).append(this.selectButton));
			
			this.panelDiv = $("<div>").addClass("Panel");
			this.pickerDiv.append(this.panelDiv);
			if(this.dataDiv){
				this.panelDiv.append(this.dataDiv);
			}
			
			this.selectText.width(this.selectBox.width() - this.selectButton.width()).outerHeight(this.selectBox.innerHeight());
			/**
			 * 注册事件
			 * 事件需要使用到this指针,指向当前的对象,需要使用bind方法进行包装和转化
			 */
			this.selectBox.click(
				bind(function(){
					this.togglePanel();
				},this)
				//bind方法执行的原理,如下
				/* function($this){
					return function(){
						$this.togglePanel();
					}
				}(this) */
			);

			if(this.option.filter){
				var filterInput = $("<input>").attr("type","text").addClass("input form-control");
				this.panelDiv.append(filterInput);
				// var inputColDiv = $("<div>").addClass("col col-md-11");
				// inputColDiv.append(filterInput);
				// var filterButton = $("<input>").attr("type","button").addClass("filterButton form-control ");
				// var buttonColDiv = $("<div>").addClass("col col-md-1");
				// buttonColDiv.append(filterButton);
				// var filterDiv = $("<div>").addClass("filterDiv").addClass("row");
				// this.panelDiv.append(filterDiv.append(inputColDiv).append(buttonColDiv));

				var filterTimeOut ;
				var filterFunction = bind(function(){
					if($.isFunction(this.option.onfilter)){
						var _filterData = this.option.onfilter.call(this , $(filterInput).val());
						if($.isFunction(this.option.convertData)){
							_filterData = this.option.convertData.call(this , _filterData);
						}
					}else{
						if(this.filterData){
							this.filterData($(filterInput).val());
						}
					}
					clearInterval(filterTimeOut);
				} , this);
				filterInput.keyup(function(){
					if(filterTimeOut){
						clearInterval(filterTimeOut);
						filterTimeOut = null;
					}
					filterTimeOut = setTimeout( filterFunction, 300);
					
				}
				);
			}

			this.dataDiv = $("<div>").addClass("dataDiv");
			this.panelDiv.append(this.dataDiv);
			/* this.panelDiv.click(function(){
				$this.hidePanel();
			}); */

			var data = this.fetchData();
			this.renderData(data);
		}
		
		AbstractPicker.prototype.showPanel = function(){
			$(this.panelDiv).show();
		}

		AbstractPicker.prototype.hidePanel = function(){
			$(this.panelDiv).hide();
		}

		AbstractPicker.prototype.togglePanel = function(){
			var status= $(this.panelDiv).is(":visible");
			if(status){
				this.hidePanel();
			}else{
				this.showPanel();
			}
		}

		AbstractPicker.prototype.putValue = function(setValue){
			$(this.submitField).val(setValue);
		}

		AbstractPicker.prototype.putText = function(setText){
			
			$(this.selectText).text(setText);
		}

		AbstractPicker.prototype.getValue = function(){
			return $(this.submitField).val();
		}

		/**
		 * data , 所有选中的数据
		 */
		AbstractPicker.prototype.selectItem = function(data){
			var valueArr = [];
			var textArr = [];
			$.each(data , function(i , n){
				valueArr.push(n.value);
				textArr.push(n.text);
			});
			this.putValue(valueArr.join(this.option.separetor));
			this.putText(textArr.join(this.option.separetor));

			if($.isFunction(this.option.onselect)){
				this.option.onselect.call(this , data);
			}
		}

		/**
		 * 对外的渲染方法
		 * 得到整个选择器的dom
		 */
		AbstractPicker.prototype.outHTML = function () {
			return this.pickerDiv;
		}

		AbstractPicker.prototype.renderTo = function (el) {
			$(el).append(this.outHTML());
			//渲染之后,才有width
			this.panelDiv.width(this.pickerDiv.width());
		}

		/**
		 * 获取数据
		 * 使用配置的option.data,进行转化
		 * 如果没有配置option.data,使用url获取,并进行转化
		 */
		AbstractPicker.prototype.fetchData = function(){
			if(this.option.data){
				if($.isFunction(this.option.convertData)){
					return this.option.convertData.call(this , this.option.data);
				}
				return this.option.data;
			}else if(this.option.url){
				var result = null;
				$.post(url , this.option.urlData , function(data){
					result = this.option.convertData.call(this , data);
				},"json");
				return result;
			}
		}

		return AbstractPicker;
	})();

	/**
	 * 简单的下拉选择
	 * 
	 */
	SimplePicker = (function(superClass){
		/**
		 * 继承父类方法
		 */
		extend(SimplePicker, superClass);
		function SimplePicker(_option){
			SimplePicker.__super__.constructor.apply(this, arguments);
		}

		//渲染数据的方法
		//每个picker子类都需要实现的方法
		SimplePicker.prototype.renderData = function(data){
			$.each(data,bind(function(i,n){
				var button = $("<div>").addClass("itemButton").addClass(this.option.mode);
				var text = $("<div>").addClass("itemText").text(n.text).attr("value",n.value);
				var panelItem = $("<div>").addClass("panelItem");
				panelItem.data("data" , n);
				panelItem.append(button).append(text);
				this.dataDiv.append(panelItem);

				panelItem.click(bind(function(event){
					if(this.option.mode == "single"){
						$(".itemButton" , this.dataDiv).removeClass("checked");
					}
					if(button.hasClass("checked")){
						button.removeClass("checked");
					}else{
						button.addClass("checked");
					}

					var dataList = [];
					$(".itemButton.checked" , this.dataDiv).each(function(index , itemButton){
						var item = $(itemButton).parent();
						dataList.push(item.data("data"));
					});

					this.selectItem(dataList);

					//对于多选组件来说,选择其中的选项的时候,不用对外进行事件冒泡,避免过多的冒泡导致panel展示不正确
					stopPropagation(event);
				},this));
			},this));
		}

		/**
		 * 过滤的方法
		 * 所有的下拉都必须实现
		*/
		SimplePicker.prototype.filterData = function(data){
			$(".panelItem" , this.dataDiv).show();

			if(data){
				var escapedQuery = data.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
				var regx = new RegExp("^(^|\\s|\\b)" + escapedQuery + "[^\\s]*");
				$(".panelItem" , this.dataDiv).each(bind(function(i , n){
					var text = $(".itemText" , n).text();
					if(!regx.test(text)){
						$(n).hide();
					}
				},this));
			}
		}

		return SimplePicker;
	})(AbstractPicker);

	/**
	 * 暴露jquery的访问方式
	 */
	$.fn.SimplePicker = function (_option) {
		var picker =  new SimplePicker(_option);
		picker.renderTo($(this));
		return picker;
	}
})();
